package cn.besbing.server.service.limsweb;

import cn.besbing.client.enums.BaseResponse;
import cn.besbing.client.enums.StatusCode;
import cn.besbing.model.entities.primary.*;
import cn.besbing.model.mapper.primary.ReportRejectInfoMapper;
import cn.besbing.server.service.general.GeneratedPrimaryKeysImpl;
import cn.besbing.server.service.general.MailServiceImpl;
import cn.besbing.server.service.primary.*;
import cn.besbing.server.utils.DataloaderLogger;
import cn.besbing.server.utils.MailDTO;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.xml.crypto.Data;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;

/**
 * 所有LIMSWEB端过来的动作服务，全部都在这个类里
 * 驳回信息表:report_reject_info
 */

@Service
public class LimsWebActionsService {

    BaseResponse baseResponse = new BaseResponse(StatusCode.SUCCESS);

    //主键生成服务接口
    @Autowired(required = false)
    private GeneratedPrimaryKeysImpl generatedPrimaryKeys;

    //报告驳回原因表接口
    @Autowired(required = false)
    private ReportRejectInfoServiceImpl rejectInfoService;

    //c_proj_task服务接口
    @Autowired(required = false)
    private PrimaryCProjTaskCoreServiceImpl cProjTaskCoreService;

    //NC委托单表头服务接口
    @Autowired(required = false)
    private PrimaryQcCmmissionHServiceImpl qcCmmissionHService;

    @Autowired(required = false)
    private PrimaryProjectServiceImpl projectService;

    @Autowired(required = false)
    private ReportDownloadInfoServiceImpl reportDownloadInfoService;

    @Autowired(required = false)
    private CustomerSqlServiceImpl customerSqlService;

    @Autowired
    private MailServiceImpl mailService;


    @Autowired(required = false)
    private RejectProcessBlobServiceImpl blobService;

    @Autowired(required = false)
    private RejectProcessDetailServiceImpl processDetailService;

    @Autowired(required = false)
    RejectProcessDetailServiceImpl detailService;

    @Autowired(required = false)
    PrimarySmuserServiceImpl smuserService;



    //委托单补全
    private Project projectInstance = null;

    //单项报告cprojtask实例
    private CProjTask singleTaskInstance = null;

    //成套报告cprojtask List实例
    private List<CProjTask> wholeTaskListInstanceList = null;

    //cprojtask的example
    CProjTaskExample cProjTaskExample = null;

    //NC委托单表头qccommissionh实例
    private QcCommissionH qcCommissionHInstance = null;

    //报告驳回实例
    private ReportRejectInfo reportRejectInfo = null;

    //报告下载实例
    private ReportDownloadInfo reportDownloadInfo = null;

    //报告下载查询实例
    private List<ReportDownloadInfo> reportDownloadInfoSearch = null;

    //报告下载条件实例
    private ReportDownloadInfoExample reportDownloadInfoExample = null;

    //不符合项明细列表
    private List<RejectProcessDetail> rejectProcessDetailList = null;

    //不符合项明细实例
    private RejectProcessDetail rejectProcessDetail = null;

    /**
     * 1、首先判断是单项还是成套，将在NC中已经『报告签发』待『报告确认』的单项任务或委托单状态回滚
     * 2、将labware中已经『报告签发』的单项任务或委托单，踢回『报告签发』处
     * @param taskcode      单据号
     * @param reporType     报告类型
     * @return
     */
    public BaseResponse reportRejectToLabwareAndNC(String taskcode,String reporType) {

        /*******
         *
         * 无论单项成套，目前REPORT_SIGN_RECORD表都没有回写
         * 等报告预览功能完成后，要返回来写这个表的回写
         * 要处理的字段有issign,isprocess
         * 可能的话，把驳回理由也加进去
         *
         */

        if ("单项".equals(reporType)){
            //Labware实例创建
            singleTaskInstance = cProjTaskCoreService.selectByTaskId(taskcode);
            projectInstance    = projectService.selectByPrimaryKey(taskcode.substring(0,12));
            if(singleTaskInstance == null || projectInstance == null)
                return new BaseResponse(-14,"Labware中未找到编号为" + taskcode + "的任务或委托单");
            //Nc实例创建
            qcCommissionHInstance = qcCmmissionHService.selectByPrimaryKey(qcCmmissionHService.getPrimary(taskcode.substring(0,12)));
            if (qcCommissionHInstance == null)
                return new BaseResponse(-14,"LIMS WEB端未找到编号为" + taskcode + "的任务或委托单");
            try{
                singleTaskInstance.setReadyForDraft("T");
                singleTaskInstance.setStatus("F");
                singleTaskInstance.setRptAuthorized("F");
                singleTaskInstance.setRptAuthorizedBy(null);
                singleTaskInstance.setRptAuthorizedOn(null);
                projectInstance.setcInvoiceVerifyed("F");
                projectInstance.setcInvoiceVerifyedBy(null);
                projectInstance.setcInvoiceVerifyedOn(null);
                qcCommissionHInstance.setDocstatus("7");
                //开始驳回写入
                DataloaderLogger.getDataloaderLogger().info("开始报告驳回，单据号:{},写入人：{}",taskcode,qcCommissionHInstance.getCreator());
                cProjTaskCoreService.updateByPrimaryKey(singleTaskInstance);
                projectService.updateByPrimaryKey(projectInstance);
                qcCmmissionHService.updateByPrimaryKey(qcCommissionHInstance);
                DataloaderLogger.getDataloaderLogger().info("结束报告驳回，单据号:{},写入人：{}",taskcode,qcCommissionHInstance.getCreator());
                baseResponse.setData(projectInstance);
            }catch (Exception e){
                //手动回滚
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return new BaseResponse(-14,"单项报告驳回发生异常：" + e.getStackTrace() + " " + e.getMessage() + " " + e.getCause() + ":" + e.getClass().getName());
            }
        }else if ("成套".equals(reporType)){
            projectInstance = projectService.selectByPrimaryKey(taskcode);
            cProjTaskExample = new CProjTaskExample();
            CProjTaskExample.Criteria criteria = cProjTaskExample.createCriteria();
            cProjTaskExample.setDistinct(true);
            cProjTaskExample.setOrderByClause("task_id asc");
            if(StringUtils.isNotBlank(taskcode)){
                criteria.andProjectEqualTo (taskcode);
                criteria.andStatusEqualTo("T");
            }
            wholeTaskListInstanceList = cProjTaskCoreService.selectByExample(cProjTaskExample);
            for (int i = 0 ; i < wholeTaskListInstanceList.size() ; i++){
                singleTaskInstance = wholeTaskListInstanceList.get(i);
                singleTaskInstance.setReadyForDraft("T");
                wholeTaskListInstanceList.set(i,singleTaskInstance);
            }
            projectInstance.setcRptAuthorized("F");
            projectInstance.setcRptAuthorizedBy(null);
            projectInstance.setcRptAuthorizedOn(null);
            try{
                for (CProjTask tempTask : wholeTaskListInstanceList){
                    cProjTaskCoreService.updateByPrimaryKey(tempTask);
                }
                projectService.updateByPrimaryKey(projectInstance);
                baseResponse.setData(projectInstance);
            }catch (Exception e){
                //手动回滚
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return new BaseResponse(-14,"成套报告驳回发生异常：" + e.getStackTrace() + " " + e.getMessage() + " " + e.getCause() + ":" + e.getClass().getName());
            }
        }else if ("不出报告".equals(reporType)){
            baseResponse = new BaseResponse(-14,"此单据报告类型为『不出报告』，无报告可以驳回");
        }
        return baseResponse;
    }

    /**
     * Report驳回记录到report_reject_info中
     * @param taskcode
     * @param rejectValue
     * @param reporType
     * @return
     */
    public BaseResponse writeReportRejectRecords(String taskcode,String rejectValue,String reporType,String rejectPerson){
        try{
            reportRejectInfo = new ReportRejectInfo();
            reportRejectInfo.setPkRejectInfo(generatedPrimaryKeys.getPrimary(20));
            //条件调用，给出当前版本号用example
            reportRejectInfo.setRejectOrder(BigDecimal.valueOf(getRejectMaxVersion(taskcode)));
            reportRejectInfo.setTaskId(taskcode);
            reportRejectInfo.setRejectInfo(rejectValue);
            //ts(建表时忘了,主键生成的地方要加一个日期格式化的调用)
            reportRejectInfo.setDef1(generatedPrimaryKeys.currentDateTime());
            //驳回人（建表时忘了）
            reportRejectInfo.setDef2(rejectPerson);
            reportRejectInfo.setDef3(null);
            reportRejectInfo.setDef4(null);
            reportRejectInfo.setDef5(null);
            rejectInfoService.insert(reportRejectInfo);
            //开始发邮件
            sendMailToRejectManager(reportRejectInfo);
            baseResponse.setData(reportRejectInfo);
        }catch(Exception e){
            //手动回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new BaseResponse(-14,"写report_reject_info时发生异常：" + e.getStackTrace() + " " + e.getMessage() + " " + e.getCause() + ":" + e.getClass().getName());
        }
        return baseResponse;
    }

    /**
     * 开始向质量负责人发送驳回通知邮件
     * @param reportRejectInfo
     * @return
     */
    public void sendMailToRejectManager(ReportRejectInfo reportRejectInfo){
        MailDTO mailDTO = new MailDTO();
        String toUser[] = new String[1];
        mailDTO.setSubject("关于单据" + reportRejectInfo.getTaskId() + "不符合项流程通知");
        String contentTitle = "";
        String content = "你好！\n";
        String sql = "select user_name from sm_user where cuserid = '" + reportRejectInfo.getDef2() + "'";
        content += "现有单据" + reportRejectInfo.getTaskId() + "于：" + reportRejectInfo.getDef1() + "被用户：" + customerSqlService.selectOne(sql) + "退回，" ;
        sql = "select nvl(mobile,'-') from bd_psndoc where pk_psndoc in (select pk_psndoc from sm_user where cuserid = '" + reportRejectInfo.getDef2() + "' )";
        content += "\n联系方式(手机)：" + customerSqlService.selectOne(sql) + ";";
        sql = "select email from bd_psndoc where pk_psndoc in (select pk_psndoc from sm_user where cuserid = '" + reportRejectInfo.getDef2() + "' )";
        content += "\n联系方式(邮箱)：" + customerSqlService.selectOne(sql) + ";";
        content += "\n退回原因：" + reportRejectInfo.getRejectInfo() + "。\n请务必尽快处理";
        try{
            //查询bd_psndoc里面mnecode(助记码为「不符合项」的记录)
            List<Map<String,Object>> rejectManagerList = customerSqlService.selectList("select name,email from bd_psndoc bp  where bp.mnecode = '质量负责人' and bp.dr = 0 and bp.enablestate = 2");
            if (rejectManagerList.size() > 0){
                for (Map<String,Object> rejectManager: rejectManagerList){
                    contentTitle = "质量负责人，" + rejectManager.get("NAME").toString() + "：\n" + content;
                    mailDTO.setContext(contentTitle);
                    toUser[0] = rejectManager.get("EMAIL").toString();
                    mailDTO.setToUsers(toUser);
                    mailService.sendMail(mailDTO);
                }
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }




    /**
     * 根据taskid获取最新的驳回版本
     * @param taskcode
     * @return
     */
    private int getRejectMaxVersion(String taskcode){
        ReportRejectInfoExample rejectInfoExample = new ReportRejectInfoExample();
        rejectInfoExample.setDistinct(true);
        rejectInfoExample.setOrderByClause(" task_id asc ");
        ReportRejectInfoExample.Criteria criteria = rejectInfoExample.createCriteria();
        criteria.andTaskIdEqualTo(taskcode);
        List<ReportRejectInfo> rejectTempList = rejectInfoService.selectByExample(rejectInfoExample);
        if (rejectTempList.size() > 0)
            return rejectTempList.size() + 1;
        else
            return 1;
    }

    /**
     * 报告下载时，将该写的信息写到report_download_info和report_reject_info(如果是不满意的话)表里
     * @param downloadInfo
     * @return
     */
    public BaseResponse DowdloadReport(String downloadInfo){
        /**
         *  逻辑：首先分解download的json，获取必要的下载信息
         *  先存report_download_info表，然后判断是否不满意，如果是不满意，则再将信息写入downloadInfo表
         *  双表回写逻辑：每次下载点击后，判断之前的报告质量和及时性两个信息字段是不是都为空？
         *  如果『是』：双表写入
         *  如果有一个不为空：断言单表写入
         */
        JSONObject json = JSON.parseObject(downloadInfo);
        reportDownloadInfo = new ReportDownloadInfo();
        reportDownloadInfoExample = new ReportDownloadInfoExample();
        ReportDownloadInfoExample.Criteria criteria = reportDownloadInfoExample.createCriteria();
        criteria.andBillnoEqualTo(json.getString("billno"));
        reportDownloadInfoSearch = reportDownloadInfoService.selectByExample(reportDownloadInfoExample);
        try{
            if (reportDownloadInfoSearch.size() < 1){
                //从未写入过满意度，需要判断是否差评
                reportDownloadInfo.setPkDownloadInfo(generatedPrimaryKeys.getPrimary(20));
                reportDownloadInfo.setTs(new Date());
                reportDownloadInfo.setBillno(json.getString("billno"));
                reportDownloadInfo.setQualityScore(json.getString("qualityscore"));
                reportDownloadInfo.setQualityReason(json.getString("qualityreason"));
                reportDownloadInfo.setAgingScore(json.getString("agingscore"));
                reportDownloadInfo.setAgingReason(json.getString("agingreason"));
                reportDownloadInfo.setDownloadCount(BigDecimal.valueOf(1));
                //获取当前db_files的版本
                reportDownloadInfo.setDownloadVersion(customerSqlService.selectOne("select file_name from (select * from db_files where description = '" + json.getString("billno") + "' order by changed_on desc) where rownum = 1 "));
                //操作人
                reportDownloadInfo.setOprator(json.getString("rejectperson"));
                int insertNum = reportDownloadInfoService.insert(reportDownloadInfo);
                if (insertNum < 1)
                    return new BaseResponse(-14,"写report_download_info时，写入记录为0");
                //report_download_info表写入正常，开始判断是否要写入report_reject_info表
                if ("不满意".equals(reportDownloadInfo.getAgingScore()) || "非常不满意".equals(reportDownloadInfo.getAgingScore())
                         || "不满意".equals(reportDownloadInfo.getQualityScore()) || "非常不满意".equals(reportDownloadInfo.getQualityScore()) ){
                    writeReportRejectRecords(reportDownloadInfo.getBillno(),"报告质量：" + reportDownloadInfo.getQualityReason() + "；报告及时性：" + reportDownloadInfo.getAgingReason(),json.getString("reportype"),reportDownloadInfo.getOprator());
                }
            }else{
                //写入过满意度，只记录下载记录
                //排序
                reportDownloadInfo = reportDownloadInfoSearch.get(0);
                for (int i = 1; i < reportDownloadInfoSearch.size() ; i++){
                     if (reportDownloadInfoSearch.get(i).getDownloadCount().compareTo(reportDownloadInfo.getDownloadCount()) == 1){
                         //当前版本大于存的版本
                         reportDownloadInfo = reportDownloadInfoSearch.get(i);
                     }
                }
                reportDownloadInfo.setPkDownloadInfo(generatedPrimaryKeys.getPrimary(20));
                reportDownloadInfo.setDownloadCount(reportDownloadInfo.getDownloadCount().add(BigDecimal.valueOf(1)));
                int insertNum = reportDownloadInfoService.insert(reportDownloadInfo);
                if (insertNum < 1)
                    return new BaseResponse(-14,"写report_download_info时，写入记录为0");
            }
        }catch (Exception e){
            //手动回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new BaseResponse(-14,"写report_download_info时发生异常：" + e.getStackTrace() + " " + e.getMessage() + " " + e.getCause() + ":" + e.getClass().getName());
        }
        return baseResponse;
    }


    /**
     * 回写reject 处理状态
     * 发邮件给处理人
     * @param jsonStr
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout = 36000,rollbackFor = Exception.class)
    public BaseResponse rejectRejectToManager(String jsonStr) {
        JSONObject strJson = JSONObject.parseObject(jsonStr);
        JSONObject jsonObject = new JSONObject();
        List<String> mailList = new ArrayList<>();
        List<String> nameList = new ArrayList<>();
        jsonObject.put("pk",strJson.getString("pk"));
        String usersArr[] = strJson.getString("users").split(";");
        String humanArr[] = null;
        MailDTO mailDTO = new MailDTO();
        for (String humanInfo : usersArr){
            humanArr = humanInfo.split(":");
            mailList.add(humanArr[1].toString() + "@hongfa.cn");
            nameList.add(humanArr[0].toString());
        }
        try{
            //开始回写
            reportRejectInfo = rejectInfoService.selectByPrimaryKey(jsonObject.getString("pk"));
            if ( StringUtils.isNotBlank(reportRejectInfo.getDef3()) || StringUtils.isNotBlank(reportRejectInfo.getDef4()) )
                return baseResponse = new BaseResponse(-14,"回写失败，该单据已经驳回过");
            //处理状态
            reportRejectInfo.setDef3("处理中");
            //处理人
            reportRejectInfo.setDef4(nameList.toString());
            int i = rejectInfoService.updateByPrimaryKey(reportRejectInfo);
            if (i < 1)
                return baseResponse = new BaseResponse(-14,"回写更新0条，请检查数据");
            mailDTO.setSubject("关于被驳回报告：" + reportRejectInfo.getTaskId() + "的处理通知");
            mailDTO.setToUsers(mailList.toArray(new String[0]));
            String content = nameList.toString() + "您好：\n";
            content += "现有单据号：" + reportRejectInfo.getTaskId() + "的报告被客户退回\n";
            content += "退回原因：" + reportRejectInfo.getRejectInfo() + "\n";
            content += "请尽快处理，谢谢！";
            mailDTO.setContext(content);
            mailService.sendMail(mailDTO);
            sendEmailToCustomer(reportRejectInfo,"process");
        }catch(Exception e){
            e.printStackTrace();
            baseResponse = new BaseResponse(-14,"回写更新出错，请检查网络:" + e.getStackTrace() + e.getCause() + e.getMessage());
        }
        return baseResponse;
    }

    /**
     * 不符合项取消动作
     * @param jsonStr 是一个jsonarray
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout = 36000,rollbackFor = Exception.class)
    public BaseResponse rejectCancelAction(String jsonStr) {
        JSONArray jsonArray = JSON.parseArray(jsonStr);
        int count = 0;
        try {
            for (ReportRejectInfo reportRejectInfo : jsonArray.toJavaList(ReportRejectInfo.class) ){
                reportRejectInfo.setDef3(null);
                reportRejectInfo.setDef4(null);
                count += rejectInfoService.updateByPrimaryKey(reportRejectInfo);
                sendEmailToCustomer(reportRejectInfo,"cancel");
            }
            baseResponse.setMsg("撤回成功，共计撤回记录" + count + "条");
        }catch (Exception e){
            baseResponse = new BaseResponse(-14,"回写更新出错，请检查网络:" + e.getStackTrace() + e.getCause() + e.getMessage());
        }finally {
            return baseResponse;
        }
    }


    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout = 36000,rollbackFor = Exception.class)
    public BaseResponse rejectConfirmAction(String jsonStr) {
        JSONArray jsonArray = JSON.parseArray(jsonStr);
        int count = 0;
        try {
            for (ReportRejectInfo reportRejectInfo : jsonArray.toJavaList(ReportRejectInfo.class) ){
                reportRejectInfo.setDef3("处理完成");
                reportRejectInfo.setDef5(generatedPrimaryKeys.currentDateTime());
                count += rejectInfoService.updateByPrimaryKey(reportRejectInfo);
                sendEmailToCustomer(reportRejectInfo,"result");
            }
            baseResponse.setMsg("确认成功，共计结项记录" + count + "条");
        }catch (Exception e){
            baseResponse = new BaseResponse(-14,"回写更新出错，请检查网络:" + e.getStackTrace() + e.getCause() + e.getMessage());
        }finally {
            return baseResponse;
        }
    }


    /**
     * 给客户发邮件通用类
     * @param reportRejectInfo
     * @param type   process：处理中  result:处理完成  cancel:取消
     */
    public void sendEmailToCustomer(ReportRejectInfo reportRejectInfo,String type){
        MailDTO mailDTO = new MailDTO();
        mailDTO.setSubject("关于单据号：" + reportRejectInfo.getTaskId() + "的报告不符合项整改的通知");
        String sqlName = "select user_name from sm_user where cuserid = '" + reportRejectInfo.getDef2() + "'";
        String customerName = customerSqlService.selectOne(sqlName);
        String sqlMail = "select email from bd_psndoc where pk_psndoc in (select pk_psndoc from sm_user where cuserid = '" + reportRejectInfo.getDef2() + "' )";
        String customerMail = customerSqlService.selectOne(sqlMail);
        String context = "尊敬的委托人 " + customerName + ":\n";
        context += "\t 你好！\n";
        context += "关于单据:" + reportRejectInfo.getTaskId() + "，您提出了'" + reportRejectInfo.getRejectInfo() + "'的建议\n";
        if ("process".equals(type)) {
            context += "不符合项流程启动时间：" + generatedPrimaryKeys.currentDateTime() + "；\n";
            context += "不符合项流程负责人：" + reportRejectInfo.getDef4() + "；\n";
        }
        if ("result".equals(type)) {
            context += "不符合项流程完成时间：" + generatedPrimaryKeys.currentDateTime() + "；\n";
            context += "不符合项流程负责人：" + reportRejectInfo.getDef4() + "；\n";
        }
        if ("cancel".equals(type)) {
            context += "不符合项流程取消时间：" + generatedPrimaryKeys.currentDateTime() + "；\n";
            context += "不符合项流程负责人：" + reportRejectInfo.getDef4() + "；\n";
        }
        mailDTO.setContext(context);
        mailDTO.setToUsers(new String[]{customerMail});
        mailService.sendMail(mailDTO);
    }

    /**
     * 获取驳回明细页数据
     * @param model
     * @param pk
     * @return
     */
    public BaseResponse createRejectDetailPageModel(Model model,String pk){
        try {
            /**
             * 变量初始化
             */
            RejectProcessDetail rejectProcessDetail = null;
            /**
             * 初始化加载的驳回表、驳回处理表、驳回处理blob表、用户表
             */
            //驳回信息表组装
            ReportRejectInfo reportRejectInfo = rejectInfoService.selectByPrimaryKey(pk);
            model.addAttribute("rejectInfo",reportRejectInfo);
            //用户model组装
            List<SmUser> smUserList = smuserService.selectRecordByUsernameZhs(SecurityUtils.getSubject().getPrincipal().toString());
            if (smUserList.size() > 0)
                model.addAttribute("user",smUserList.get(0));
            else
                model.addAttribute("user",new SmUser());
            //驳回处理明细表组装
            List<RejectProcessDetail> detailList = detailService.selectRecordByBillno(reportRejectInfo.getTaskId());
            if (detailList.size() > 0) {
                //rejectProcessDetail.setModifyer(smUserList.get(0).getCuserid());
                //rejectProcessDetail.setModifytime(generatedPrimaryKeys.currentDateTime());
                model.addAttribute("detail", detailList.get(0));
            } else {
                //如果没有开始初始化，给值
                rejectProcessDetail = new RejectProcessDetail();
                rejectProcessDetail.setSourceBillPk(reportRejectInfo.getPkRejectInfo());
                rejectProcessDetail.setBillno(reportRejectInfo.getTaskId());
                rejectProcessDetail.setReceiver(smUserList.get(0).getCuserid());
                rejectProcessDetail.setReceivetime(generatedPrimaryKeys.currentDateTime());
                rejectProcessDetail.setModifyer(smUserList.get(0).getCuserid());
                rejectProcessDetail.setModifytime(generatedPrimaryKeys.currentDateTime());
                rejectProcessDetail.setProcessText("");
                rejectProcessDetail.setSubmiter("");
                rejectProcessDetail.setSubmitime("");
                rejectProcessDetail.setTs(generatedPrimaryKeys.currentDateTime());
                model.addAttribute("detail", rejectProcessDetail);
            }
            //明细表附件表组装,可能有多个附件
            List<RejectProcessBlob> blobList = new ArrayList<>();
            if (rejectProcessDetail.getPkProcessDetail() != null ){
                blobList = blobService.selectRecordByDetailPk(rejectProcessDetail.getPkProcessDetail());
                model.addAttribute("blob", blobList);
            }else {
                model.addAttribute("blob",new RejectProcessBlob());
            }
            baseResponse.setMsg("OK");
            baseResponse.setData(model);
        }catch (Exception e){
            baseResponse = new BaseResponse(-14,"查询出错:" + e.getStackTrace() + e.getCause() + e.getMessage());
            DataloaderLogger.getDataloaderLogger().error("查询出错:" + e.getStackTrace() + e.getCause() + e.getMessage());
        }finally {
            return baseResponse;
        }
    }

    /**
     * 不符合项上传文件服务
     * @param file
     * @return
     */
    public synchronized BaseResponse rejectUploadFilesService(MultipartFile file ) {
        try{
            InputStream inputStream = file.getInputStream();
            byte[] data = readInputStream(inputStream);
            DataloaderLogger.getDataloaderLogger().info("======执行了上传文件处理======");
            baseResponse.setCode(0);
        }catch(Exception e){
            DataloaderLogger.getDataloaderLogger().error("不符合上传文件发生错误，原因：" +e.getMessage() + e.getCause() + e.getStackTrace());
            baseResponse = new BaseResponse(-14,"不符合上传文件发生错误，原因：" +e.getMessage() + e.getCause() + e.getStackTrace());
        }finally {
            return baseResponse;
        }
    }


    /**
     * 工具类
     * @param inStream
     * @return
     * @throws Exception
     */
    public static byte[] readInputStream(InputStream inStream) throws Exception {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        //创建一个Buffer字符串 
        byte[] buffer = new byte[1024];
        //每次读取的字符串长度，如果为-1，代表全部读取完毕 
        int len = 0;
        //使用一个输入流从buffer里把数据读取出来 
        while ((len = inStream.read(buffer)) != -1) {
            //用输出流往buffer里写入数据，中间参数代表从哪个位置开始读，len代表读取的长度 
            outStream.write(buffer, 0, len);
        }
        //关闭输入流 
        inStream.close();
        byte[] returnVar = outStream.toByteArray();
        outStream.flush();
        outStream.close();
        //把outStream里的数据写入内存 
        return returnVar;
    }


    /**
     * 不符合项明细保存动作
     * @param jsonStr
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout = 36000,rollbackFor = Exception.class)
    public BaseResponse saveRejectDetail(String jsonStr) {
        baseResponse = new BaseResponse(StatusCode.SUCCESS);
        try{
            String ts = generatedPrimaryKeys.currentDateTime();
            JSONObject jsonObject = JSONObject.parseObject(jsonStr);
            rejectProcessDetailList = new ArrayList<>();
            //判断是不是已经存在驳回明细，没有新增，有的话更新
            RejectProcessDetailExample rejectProcessDetailExample = new RejectProcessDetailExample();
            RejectProcessDetailExample.Criteria criteria = rejectProcessDetailExample.createCriteria();
            //criteria.andBillnoEqualTo(jsonObject.getString("taskIdCode"));
            criteria.andSourceBillPkEqualTo(jsonObject.getString("sourcePkId"));
            rejectProcessDetailList = detailService.selectRecordByBillno(jsonObject.getString("taskIdCode"));
            if (rejectProcessDetailList.size() > 0){
                //更新
                rejectProcessDetail = rejectProcessDetailList.get(0);
                rejectProcessDetail.setModifyer(jsonObject.getString("user"));
                rejectProcessDetail.setModifytime(ts);
                rejectProcessDetail.setTs(ts);
                rejectProcessDetail.setProcessText(jsonObject.getString("textArea"));
                //detailService.updateByPrimaryKey(rejectProcessDetail);
                detailService.updateByPrimaryKeySelective(rejectProcessDetail);
            }else {
                //插入
                rejectProcessDetail = new RejectProcessDetail();
                rejectProcessDetail.setPkProcessDetail(generatedPrimaryKeys.getPrimary(20));
                rejectProcessDetail.setSourceBillPk(jsonObject.getString("sourcePkId"));
                rejectProcessDetail.setBillno(jsonObject.getString("taskIdCode"));
                rejectProcessDetail.setModifyer(jsonObject.getString("user"));
                rejectProcessDetail.setReceiver(jsonObject.getString("user"));
                rejectProcessDetail.setReceivetime(ts);
                rejectProcessDetail.setModifytime(ts);
                rejectProcessDetail.setTs(ts);
                rejectProcessDetail.setProcessText(jsonObject.getString("textArea"));
                detailService.insert(rejectProcessDetail);
            }
            baseResponse.setMsg(rejectProcessDetail.getPkProcessDetail());
        }catch (Exception e){
            DataloaderLogger.getDataloaderLogger().error("不符合明细保存发生错误，原因：" +e.getMessage() + e.getCause() + e.getStackTrace());
            baseResponse = new BaseResponse(-14,"不符合明细保存发生错误，原因：" +e.getMessage() + e.getCause() + e.getStackTrace());
        }finally {
            return baseResponse;
        }
    }

    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout = 36000,rollbackFor = Exception.class)
    public BaseResponse commitRejectDetail(String jsonStr) {
        baseResponse = new BaseResponse(StatusCode.SUCCESS);
        try{
            String ts = generatedPrimaryKeys.currentDateTime();
            JSONObject jsonObject = JSONObject.parseObject(jsonStr);
            //reportRejectInfo = new ReportRejectInfo();
            reportRejectInfo = rejectInfoService.selectByPrimaryKey(jsonObject.getString("sourcePkId"));
            rejectProcessDetailList = new ArrayList<>();
            //判断是不是已经存在驳回明细，没有新增，有的话更新
            rejectProcessDetailList = detailService.selectRecordByBillno(jsonObject.getString("taskIdCode"));
            if (rejectProcessDetailList.size() > 0)
                rejectProcessDetail = rejectProcessDetailList.get(0);
            else
                baseResponse = new BaseResponse(-14,"提交失败，原因：未找到" + jsonObject.getString("taskIdCode") +"所属明细单");
            if ( reportRejectInfo != null){
                reportRejectInfo.setDef3("提交审核");

                rejectProcessDetail.setTs(ts);
                rejectProcessDetail.setSubmitime(ts);
                rejectProcessDetail.setSubmiter(jsonObject.getString("user"));

                rejectInfoService.updateByPrimaryKey(reportRejectInfo);
                detailService.updateByPrimaryKeySelective(rejectProcessDetail);


                //开始发邮件
                //查询bd_psndoc里面mnecode(助记码为「不符合项」的记录)
                MailDTO mailDTO = new MailDTO();
                String toUser[] = new String[1];
                mailDTO.setSubject("关于单据" + reportRejectInfo.getTaskId() + "不符合项流程通知");
                String contentTitle = "";
                String content = "你好！\n";
                String context = "关于单据"+ jsonObject.getString("taskIdCode") +"的不符合项问题，当前已由" + jsonObject.getString("user") + "提交审核，请尽快处理。";
                List<Map<String,Object>> rejectManagerList = customerSqlService.selectList("select name,email from bd_psndoc bp  where bp.mnecode = '质量负责人' and bp.dr = 0 and bp.enablestate = 2");
                if (rejectManagerList.size() > 0){
                    for (Map<String,Object> rejectManager: rejectManagerList){
                        contentTitle = "质量负责人，" + rejectManager.get("NAME").toString() + "：\n" + content;
                        mailDTO.setContext(contentTitle);
                        toUser[0] = rejectManager.get("EMAIL").toString();
                        mailDTO.setToUsers(toUser);
                        mailDTO.setContext(context);
                        mailService.sendMail(mailDTO);
                    }
                }

            }else {
                baseResponse = new BaseResponse(-14,"提交失败，原因：未找到" + jsonObject.getString("taskIdCode") + "所属不符合项的主单据");
            }
        }catch (Exception e){
            DataloaderLogger.getDataloaderLogger().error("不符合明细保存发生错误，原因：" +e.getMessage() + e.getCause() + e.getStackTrace());
            baseResponse = new BaseResponse(-14,"不符合明细保存发生错误，原因：" +e.getMessage() + e.getCause() + e.getStackTrace());
        }finally {
            return baseResponse;
        }
    }


    /**
     * 不符合项处理结果退回处理人
     * @param jsonStr
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout = 36000,rollbackFor = Exception.class)
    public BaseResponse rejectProcessToProcessor(String jsonStr) {
        try{
            JSONObject jsonObject = JSONObject.parseObject(jsonStr);
            reportRejectInfo = rejectInfoService.selectByPrimaryKey(jsonObject.getString("taskIdCode"));
            if (reportRejectInfo!=null){
                reportRejectInfo.setDef3("处理中");
                rejectInfoService.updateByPrimaryKey(reportRejectInfo);
                String nameStr = reportRejectInfo.getDef4().replace("[","");
                nameStr = nameStr.replace("]","");
                String nameArr[] = nameStr.split(",");
                for(int i=0; i<nameArr.length;i++){
                    String cuserid = smuserService.selectUserByName(nameArr[i].trim());
                    SmUser smUser = smuserService.selectByPrimaryKey(cuserid);
                    MailDTO mailDTO = new MailDTO();
                    String toUser[] = new String[1];
                    toUser[0] = smUser.getEmail();
                    mailDTO.setSubject("关于单据" + reportRejectInfo.getTaskId() + "不符合项流程处理结果被退回的通知");
                    mailDTO.setToUsers(toUser);
                    String context = "退回原因：" + jsonObject.getString("rejectedResult");
                    mailDTO.setContext(context);
                    mailService.sendMail(mailDTO);
                }
            }else {
                baseResponse = new BaseResponse(-14,"退回失败，原因：未找到主键为" + jsonObject.getString("taskid") + "所属不符合项的主单据");
            }
        }catch (Exception e){
            DataloaderLogger.getDataloaderLogger().error("不符合明细保存发生错误，原因：" +e.getMessage() + e.getCause() + e.getStackTrace());
            baseResponse = new BaseResponse(-14,"不符合明细保存发生错误，原因：" +e.getMessage() + e.getCause() + e.getStackTrace());
        }finally {
            return baseResponse;
        }
    }
}
